#include <aio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define MSG_SIZE (8 + 4 + 4096)
#define PIPE_NAME "/tmp/client_server_pipe"
#define DATA_FILE "data.txt"

// 异步写文件上下文
struct aio_context {
  struct aiocb cb;
  char buffer[128];
};

// 检查消息完整性
int check_message_integrity(char *msg) {
  // 检查后4096字节是否全为0
  for (int i = 12; i < MSG_SIZE; i++) {
    if (msg[i] != 0)
      return 0;
  }
  return 1;
}

// 异步写文件回调
void write_to_file(long long src_tid, int seq) {
  struct aio_context *ctx = malloc(sizeof(struct aio_context));
  snprintf(ctx->buffer, sizeof(ctx->buffer), "%lld %d\n", src_tid, seq);

  // 设置异步写请求
  memset(&ctx->cb, 0, sizeof(struct aiocb));
  ctx->cb.aio_fildes = open(DATA_FILE, O_WRONLY | O_CREAT | O_APPEND, 0666);
  ctx->cb.aio_buf = ctx->buffer;
  ctx->cb.aio_nbytes = strlen(ctx->buffer);
  ctx->cb.aio_offset = 0;

  if (aio_write(&ctx->cb) == -1) {
    perror("aio_write failed");
    close(ctx->cb.aio_fildes);
    free(ctx);
    return;
  }

  // 等待异步写完成
  while (aio_error(&ctx->cb) == EINPROGRESS) {
    usleep(100);
  }

  close(ctx->cb.aio_fildes);
  free(ctx);
}

int main() {
  // 打开管道
  int fd = open(PIPE_NAME, O_RDONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("Open pipe failed");
    return 1;
  }

  // 设置异步读
  struct aiocb cb;
  char msg[MSG_SIZE];
  memset(&cb, 0, sizeof(struct aiocb));
  cb.aio_fildes = fd;
  cb.aio_buf = msg;
  cb.aio_nbytes = MSG_SIZE;

  // 事件驱动循环
  while (1) {
    if (aio_read(&cb) == -1) {
      perror("aio_read failed");
      continue;
    }

    // 等待异步读完成
    while (aio_error(&cb) == EINPROGRESS) {
      usleep(100);
    }

    int ret = aio_return(&cb);
    if (ret == MSG_SIZE) {
      if (check_message_integrity(msg)) {
        long long src_tid = *(long long *)msg;
        int seq = *(int *)(msg + 8);
        write_to_file(src_tid, seq);
      } else {
        fprintf(stderr, "Invalid message received\n");
      }
    } else if (ret == 0) {
      // EOF，管道关闭
      break;
    }
  }

  close(fd);
  return 0;
}
